#include "ser_dep_transport.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

uint16_t ATT_MTU = 23;

ser_dep_serialized_t *ser_dep_serialize(ser_dep_serializer_ctx_t *ctx, uint8_t *payload,
                                        uint16_t len) {
    uint16_t max_payload = ser_dep_get_max_payload(); /* Max payload without fragment header byte */
    uint16_t bytes_left = len;
    uint16_t packets = (len / max_payload) + 1;
    ctx->s = malloc(sizeof(ser_dep_serialized_t) * packets);
    ser_dep_serialized_t *p = ctx->s;
    for (int packet = 0; packet < packets; packet++) {
        p->frame = malloc(sizeof(ser_dep_frame_t));
        p->frame->payload.payload = malloc(max_payload);
        p->next = NULL;
        if (packet < packets - 1) {
            p->next = p + 1;
        }
        if (bytes_left > (max_payload)) {
            p->frame->len = max_payload;
        } else {
            p->frame->len = bytes_left;
        }

        for (int i = 0; i < max_payload; i++) {
            p->frame->payload.payload[i] = payload[i + max_payload * packet];
        }

        p->frame->payload.header =
            ((packet == 0) ? FRAGMENT_INITIAL : FRAGMENT_INTERMEDIATE) |
            ((packet == packets - 1) ? FRAGMENT_FINAL : FRAGMENT_INTERMEDIATE) |
            (packets - packet - 1);

        bytes_left -= p->frame->len;
        p = p->next;
    }
    return ctx->s;
}

uint16_t ser_dep_get_max_payload(void) {
    return ATT_MTU - 3 - 1; /* Max payload without fragment header byte */
}

void ser_dep_destroy_serializer_ctx(ser_dep_serializer_ctx_t *ctx) { free(ctx->s); }

bool ser_dep_is_first_fragment(uint8_t const fragment_header) {
    if (fragment_header & FRAGMENT_INITIAL) {
        return true;
    }
    return false;
}

bool ser_dep_is_last_fragment(uint8_t const fragment_header) {
    if (fragment_header & FRAGMENT_FINAL) {
        return true;
    }
    return false;
}